package middleware

import (
	"encoding/json"
	"github.com/kataras/iris"
	"github.com/kataras/iris/websocket"
	"net/http"
	"sync"
)

var PipelineWsServerRs *PipelineWsServer
var PipelineInitOnce sync.Once
var lock sync.RWMutex
var Conn = make(map[string]map[websocket.Connection]bool) //在线链接map

type PipelineWsServer struct {
	ServerRs *websocket.Server
}

/**
注册webscoket
*/
func GetPipelineWsServer() *PipelineWsServer {
	PipelineInitOnce.Do(func() {
		PipelineWsServerRs = &PipelineWsServer{}
		PipelineWsServerRs.ServerRs = websocket.New(websocket.Config{
			EvtMessagePrefix: []byte(""),
			ReadBufferSize:   1024, //指定读缓存区大小
			WriteBufferSize:  1024, // 指定写缓存区大小
			CheckOrigin: func(r *http.Request) bool { //解决跨域问题
				return true
			},
		})
	})
	return PipelineWsServerRs
}

/**
数据接收
*/
func (w *PipelineWsServer) ReceiveMessage() {
	//绑定接收数据处理
	w.ServerRs.OnConnection(func(ws websocket.Connection) {
		userId := ws.Context().URLParamDefault("userId", "")
		if userId == "" {
			_ = ws.Disconnect()
			return
		}
		JoinUserList(userId, ws)
		ws.SetValue("userId", userId)
		ws.OnMessage(func(data []byte) {

		})
		ws.OnDisconnect(func() {
			userId := ws.GetValueString("userId")
			if userId != "" {
				//删除链接至map
				lock.Lock()
				if _, ok := Conn[userId][ws]; ok {
					delete(Conn[userId], ws)
					if len(Conn[userId]) == 0 {
						delete(Conn, userId)
					}
				}
				lock.Unlock()
			}
		})
	})
}

/*
 账号多端登录处理
*/
func JoinUserList(userId string, ws websocket.Connection) {
	lock.Lock()
	if _, ok := Conn[userId]; !ok {
		Conn[userId] = make(map[websocket.Connection]bool)
	}
	Conn[userId][ws] = true
	lock.Unlock()
}

/**
数据推送
*/
func (w *PipelineWsServer) PushMessage(userId string, message string) error {
	lock.RLock()
	if conn, ok := Conn[userId]; ok {
		for k, _ := range conn {
			checkClient := w.ServerRs.GetConnection(k.ID())
			msg := iris.Map{
				"code": iris.StatusOK,
				"msg":  message,
			}
			buf, _ := json.Marshal(msg)
			_ = checkClient.EmitMessage(buf)
		}
	}
	lock.RUnlock()
	return nil
}

/*
推送所有
*/
func (w *PipelineWsServer) PushMessageAll(message string) error {
	for _, conn := range w.ServerRs.GetConnections() {
		msg := iris.Map{
			"code": iris.StatusOK,
			"msg":  message,
		}
		buf, _ := json.Marshal(msg)
		_ = conn.EmitMessage(buf)
	}
	return nil
}
